import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
class OrderedStatement
{
    private final int id;
    private Statement statement;
    OrderedStatement(Statement statement, int id)
    {
        this.statement = statement;
        this.id = id;
    }
    public int getId()
    {
        return id;
    }
    public ResultSet executeQuery(String sql) throws SQLException
    {
        return statement.executeQuery(sql);
    }
    public boolean execute(String sql) throws SQLException
    {
        return statement.execute(sql);
    }
    public boolean execute(String sql, int[] colomnIndexes) throws SQLException
    {
        return statement.execute(sql, colomnIndexes);
    }
    public void addBatch(String sql) throws SQLException
    {
        statement.addBatch(sql);
    }
    public int[] executeBatch() throws SQLException
    {
        return statement.executeBatch();
    }
    void close() throws SQLException
    {
        statement.close();
    }
    public void cancle() throws SQLException
    {
        statement.cancel();
    }
    public void clearBatch() throws SQLException
    {
        statement.clearBatch();
    }
    public void clearWarnings() throws SQLException
    {
        statement.clearWarnings();
    }
    public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
    {
        return statement.execute(sql, autoGeneratedKeys);
    }
    public boolean execute(String sql, String[] columnNames) throws SQLException
    {
        return statement.execute(sql, columnNames);
    }
}
public class Resources
{
    private final int countOfResources = 3;
    private Connection connection;
    private Statement[] statements = new Statement[countOfResources];
    private ArrayList<Integer> availableStatements = new ArrayList<>(countOfResources);
    private Resources() throws SQLException
    {
        connection = DriverManager.getConnection(
                "jdbc:sqlserver://localhost;DatabaseName=evaluations_of_teachers",
                "xiF616", "L'hospital");
        for (int i = 0; i < statements.length; ++i)
        {
            statements[i] = connection.createStatement();
            availableStatements.add(i);
        }
    }
    private OrderedStatement getStatement(Resources instance) throws SQLException
    {
        int order;
        synchronized (instance.availableStatements)
        {
            while (instance.availableStatements.isEmpty())
                try
                {
                    instance.availableStatements.wait();
                }
                catch (InterruptedException e)
                {
                }
        }
        order = instance.availableStatements.remove(instance.availableStatements.size() - 1);
        return new OrderedStatement(instance.statements[order], order);
    }
    private void toRelease(Resources instance, OrderedStatement orderedStatement)//千万不可以关statement，关了以后就不能用了
    {
        synchronized (instance.availableStatements)
        {
            availableStatements.add(orderedStatement.getId());
            instance.availableStatements.notify();
        }
    }
    protected void close(Resources instance)
    {
        for (Statement statement : instance.statements)
            try
            {
                statement.close();
            }
            catch (SQLException throwables)
            {}
        try
        {
           instance.connection.close();
        }
        catch (SQLException throwables)
        {}
    }

    private static Resources instance;
    private static SQLException sqlException = null;
    static
    {
        try
        {
            instance = new Resources();
        }
        catch (SQLException throwables)
        {
            sqlException = throwables;
        }
    }
    public static void testException() throws SQLException
    {
        if (sqlException != null)
            throw sqlException;
    }
    public static OrderedStatement getStatement() throws SQLException
    {
        return instance.getStatement(instance);
    }
    public static void close()
    {
        instance.close(instance);
    }
    public static void toRelease(OrderedStatement orderedStatement)
    {
        if (orderedStatement != null)
            instance.toRelease(instance, orderedStatement);
    }
}
